/*********************************************************************
 *
 *  base64conversion
 *
 *********************************************************************
 *
 * FileName:        base64conversion.c
 * Processor:       PIC18, PIC24F, PIC24H, dsPIC30, dsPIC33F
 * Complier:        Microchip C18 v3.03 or higher
 * 					Microchip C30 v2.02 or higher
 *
 * Based upon:
 * http://users.fmrib.ox.ac.uk/~crodgers/netgear/base64-encode.c
 * http://users.fmrib.ox.ac.uk/~crodgers/netgear/base64-decode.c
 *
 ********************************************************************/
#define __BASE64CONVERSION_C

#include <string.h>
#include <stdlib.h>
#include "GenericTypeDefs.h"
#include "Compiler.h"
#include "HardwareProfile.h"

const rom BYTE alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

void base64encode(BYTE *inputData, BYTE *outputData)
{
    unsigned int char_count, i, o;
    DWORD bits;

    char_count = 0;
    bits = 0;
	i = 0;
	o = 0;
    while( inputData[i] != '\0') {
		bits += inputData[i];
		char_count++;
		if (char_count == 3) {
			outputData[o++] = alphabet[(bits >> 18) & 0x3f];
		    outputData[o++] = alphabet[(bits >> 12) & 0x3f];
		    outputData[o++] = alphabet[(bits >> 6) & 0x3f];
		    outputData[o++] = alphabet[bits & 0x3f];
		    bits = 0;
		    char_count = 0;
		} else {
		    bits <<= 8;
		}
		i++;
	}
    if (char_count != 0) {
		bits <<= 16 - (8 * char_count);
		outputData[o++] = alphabet[(bits >> 18) & 0x3f];
		outputData[o++] = alphabet[(bits >> 12) & 0x3f];
		if (char_count == 1) {
		    outputData[o++] = '=';
		    outputData[o++] = '=';
		} else {
		    outputData[o++] = alphabet[(bits >> 6) & 0x3f];
		    outputData[o++] = '=';
		}
	}
	outputData[o++] = '\0';
}

/*
void base64decode(BYTE *inputData, BYTE *outputData, BOOL errorFlag)
{
    BYTE inalphabet[64], decoder[64];
    //BYTE inalphabet[256], decoder[256];
    int i, bits, char_count, o;

    for (i = (sizeof alphabet) - 1; i >= 0 ; i--) {
		inalphabet[alphabet[i]] = 1;
		decoder[alphabet[i]] = i;
    }

    char_count = 0;
    bits = 0;
	i = 0;
	o = 0;
	errorFlag = FALSE;
    while( inputData[i] != '\0') {
		if (inputData[i] == '=')
			break;
		if (inputData[i] > 255 || ! inalphabet[inputData[i]])
			continue;
		bits += decoder[inputData[i]];
		char_count++;
		if (char_count == 4) {
			outputData[o++] = (bits >> 16);
		    outputData[o++] = ((bits >> 8) & 0xff);
		    outputData[o++] = (bits & 0xff);
		    bits = 0;
		    char_count = 0;
		} else {
		    bits <<= 6;
		}
		i++;
    }
    if (inputData[i] == '\0') {
		if (char_count) {
		    //fprintf(stderr, "base64 encoding incomplete: at least %d bits truncated", ((4 - char_count) * 6));
		    errorFlag = TRUE;
		}
    } else { //c == '=' 
		switch (char_count) {
		  case 1:
		  	//fprintf(stderr, "base64 encoding incomplete: at least 2 bits missing");
		    errorFlag = TRUE;
		    break;
		  case 2:
		    outputData[o++] = (bits >> 10);
		    break;
		  case 3:
		    outputData[o++] = (bits >> 16);
		    outputData[o++] = ((bits >> 8) & 0xff);
		    break;
		}
    }
}
*/